package ac.manchester.cs.afzal.tcm_processing.terms_sentence_handler;

import ac.manchester.cs.afzal.tcm_processing.miscellaneous.File_Manager_Impl;

import java.net.URL;

import gate.*;
import gate.creole.ANNIEConstants;
import gate.creole.SerialAnalyserController;
import gate.util.GateException;
import gate.util.Out;
import java.io.*;
import java.util.*;



/**
 * Term_Lookup_Implements Terms Look and Sentence Boundary Marking using Gate.
 * The terms list(s) (as .lst file) is/are loaded manually in Gate's gazetteer.
 * The input directory list for corpus and output (annotated) documents list can be given as
 * directory paths.
 *
 * (This class is used with
 * (i) Terms recognised using ATR.
 * (ii) The GAD List of Diseases (manually created).
 *
 * Parameter values in properties file are to be changed depending on the source of lookup terms.
 *
 * Warning: This file gives out of memory error. However, the processed files can be removed from
 * input directory and process can be re-run on remaining un processed files.
 * 
 * @author Hammad Afzal
 * @version 1.0
 * Last Modification Date: 16 Jan, 2012
  */
public class Term_Lookup_Impl
{

    private String MODE = "MODE";

    private String GATE_HOME = "GATE_HOME";
    private String GAZETTEER_LIST_PATH = "GAZETTEER_LIST_PATH";

    private String ANNOTATED_DOCUMENTS_CORPUS = "ANNOTATED_DOCUMENTS_CORPUS";
    private String ANNOTATED_DOCUMENTS_TRAINING = "ANNOTATED_DOCUMENTS_TRAINING";
    
    private String DOCUMENTS_CORPUS = "DOCUMENTS_CORPUS";
    private String DOCUMENTS_TRAINING = "DOCUMENTS_TRAINING";

    private SerialAnalyserController annieController;
    File_Manager_Impl fileManager;

    public Term_Lookup_Impl()
    {
        Properties props = new Properties();
        try
        {
            props.load(new FileInputStream("Term_Classification.properties"));
        }
        catch (Exception ex)
        {
            System.out.println("Exception while loading propoerties : " + ex.getCause());
        }

        /************************ Gate Initialising ***********************************************/
        GATE_HOME = props.getProperty(GATE_HOME);
        GAZETTEER_LIST_PATH = props.getProperty(GAZETTEER_LIST_PATH);

        MODE = props.getProperty(MODE);

        ANNOTATED_DOCUMENTS_CORPUS = props.getProperty(ANNOTATED_DOCUMENTS_CORPUS);
        ANNOTATED_DOCUMENTS_TRAINING = props.getProperty(ANNOTATED_DOCUMENTS_TRAINING);

        DOCUMENTS_CORPUS = props.getProperty(DOCUMENTS_CORPUS);
        DOCUMENTS_TRAINING = props.getProperty(DOCUMENTS_TRAINING);
    }

    public void initAnnie() throws GateException
    {
        Out.prln("Initialising Sentence Splitter & Gazetteer...");
        annieController = (SerialAnalyserController) Factory.createResource("gate.creole.SerialAnalyserController", Factory.newFeatureMap(), Factory.newFeatureMap(), "ANNIE_" + Gate.genSym());
        FeatureMap params = Factory.newFeatureMap(); // use default parameters
        ProcessingResource pr0 = (ProcessingResource) Factory.createResource(ANNIEConstants.PR_NAMES[1], params);
        annieController.add(pr0);
        ProcessingResource pr1 = (ProcessingResource) Factory.createResource(ANNIEConstants.PR_NAMES[3], params);
        annieController.add(pr1);
        ProcessingResource pr2 = (ProcessingResource) Factory.createResource(ANNIEConstants.PR_NAMES[2], params);
        annieController.add(pr2);
        Out.prln("...Gazetter & Sentence Splitter Loaded...");
    }

    public void setCorpus(Corpus corpus)
    {
        annieController.setCorpus(corpus);
    }

    public void execute() throws GateException
    {
        Out.prln("Running Annie (Tokenizer/Gazetteer/Sentence Splitter)");
        annieController.execute();
        Out.prln("...Annie Process (Tokenizer/Gazetteer/Sentence Splitter) Completed");
    }

    public void term_lookup_and_sentence_boundry_mark(boolean isSingleLstFile) throws GateException, IOException, java.lang.Exception
    {
        Properties props2 = System.getProperties();
        props2.put("gate.home", GATE_HOME);
        Out.prln("Initialising GATE...");
        Gate.init();

        // Load ANNIE plugin
        File gateHome = Gate.getGateHome();
        File pluginsHome = new File(gateHome, "plugins");
        Gate.getCreoleRegister().registerDirectories(new File(pluginsHome, "ANNIE").toURL());
        Out.prln("...GATE initialised");

        int no_of_files;
        String[] corpus_files;
        File corpus_dir,file_name;
        String corpus_dir_name = "";

        /************************ Gate Initialising Done *******************************************/
        corpus_dir_name = (MODE.equals("Training")) ? DOCUMENTS_TRAINING : DOCUMENTS_CORPUS;
        corpus_dir = new File(corpus_dir_name);
        corpus_files = corpus_dir.list();
        no_of_files = corpus_files.length;

        for(int i = 0; i < no_of_files; i ++)
        {
            /*
            if( ! (isSingleLstFile))
            {
                try
                {
                    BufferedWriter out = new BufferedWriter(new FileWriter(GAZETTEER_LIST_PATH + "//lists.def"));
                    String list_editor = corpus_files[i].substring(0, corpus_files[i].length() - 4) + ".lst:" + corpus_files[i].substring(0, corpus_files[i].length() - 4);
                    out.write(list_editor);
                    out.close();
                }
                catch (IOException e)
                {
                }
            }
            */
            initAnnie();

            /********************* Making Corpus /*********************/
            Corpus corpus = (Corpus) Factory.createResource("gate.corpora.CorpusImpl");

            corpus_dir_name = (MODE.equals("Training")) ? DOCUMENTS_TRAINING : DOCUMENTS_CORPUS;
            file_name = (MODE.equals("Corpus"))? new File(DOCUMENTS_CORPUS + corpus_files[i]):new File(DOCUMENTS_TRAINING + corpus_files[i]);


            file_name = file_name.getAbsoluteFile();
            URL u = file_name.toURL();
            FeatureMap params = Factory.newFeatureMap();
            params.put("sourceUrl", u);
            params.put("preserveOriginalContent", new Boolean(true));
            params.put("collectRepositioningInfo", new Boolean(true));
            Document doc = (Document) Factory.createResource("gate.corpora.DocumentImpl", params);
            corpus.add(doc);

            /********************* Making Corpus End /*********************/
            setCorpus(corpus);
            execute();

            Iterator iter = corpus.iterator();
            while(iter.hasNext())
            {
                Document doc1 = (Document) iter.next();
                AnnotationSet defaultAnnotSet = doc.getAnnotations();
                Set annotTypesRequired = new HashSet();
                annotTypesRequired.add("Sentence");
                annotTypesRequired.add("Lookup");
                AnnotationSet annotations = defaultAnnotSet.get(annotTypesRequired);
                String xmlDocument = doc1.toXml(annotations, false);

                String fileName;
                if(MODE.equals("Corpus"))
                {
                    fileName = new String(ANNOTATED_DOCUMENTS_CORPUS + "//" + corpus_files[i].substring(0, corpus_files[i].length() - 4) + ".XML");
                }
                else
                {
                    fileName = new String(ANNOTATED_DOCUMENTS_TRAINING + "//" + corpus_files[i].substring(0, corpus_files[i].length() - 4) + ".XML");
                }

                FileWriter writer = new FileWriter(fileName);
                writer.write(xmlDocument);
                writer.close();
            }
            Factory.deleteResource(doc);
            corpus.clear();
        }
    }
}
